import Vue from 'vue'
import axios from 'axios'
import store from '@/store'
import notification from 'ant-design-vue/es/notification'
import { VueAxios } from './axios'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { aes, sign } from '@/utils/security'

// 创建 axios 实例
const service = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL, // api base_url
  timeout: 6000 // 请求超时时间
})

const requestFailed = (error) => {
  notification['warning']({
    message: '错误',
    description: ((error.response || {}).data || {}).message || '请求出现错误，请稍后再试',
    duration: 4
  })
}

const err = (error) => {
  console.log(error.response)
  if (error.response) {
    const data = error.response.data
    const token = Vue.ls.get(ACCESS_TOKEN)
    if (error.response.status === 403) {
      notification.error({
        message: 'Forbidden',
        description: data.message
      })
    }
    if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
      notification.error({
        message: 'Unauthorized',
        description: 'Authorization verification failed'
      })
      if (token) {
        store.dispatch('Logout').then(() => {
          setTimeout(() => {
            window.location.reload()
          }, 1500)
        })
      }
    }
    if (error.response.status === 400) {
      requestFailed(error)
    }
    if (error.response.status === 500) {
      notification['warning']({
        message: '服务异常',
        description: '请求出现错误，请稍后再试',
        duration: 4
      })
    }
  }
  return Promise.reject(error)
}

// request interceptor
service.interceptors.request.use(config => {
  const token = Vue.ls.get(ACCESS_TOKEN)
  if (token) {
    config.headers['Access-Token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
  }
  return config
}, err)

// response interceptor
service.interceptors.response.use((response) => {
  return response.data
}, err)

const installer = {
  vm: {},
  install (Vue) {
    Vue.use(VueAxios, service)
  }
}

/**
 * get方式请求，url传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const get = (url, params, level) =>
  service(getConfig(url, 'get', true, params, level))
    .then(res => successback(res))
/**
 * post方式请求 json方式传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const postJson = (url, params, level) =>
  service(getConfig(url, 'post', true, params, level))
  .then(res => successback(res))
/**
 * post方式请求 表单传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const post = (url, params, level) => service(getConfig(url, 'post', false, params, level))
  .then(res => successback(res))
/**
 * delete方式请求 url传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const del = (url, params, level) =>
  service(getConfig(url, 'delete', true, params, level))
  .then(res => successback(res))
/**
 * put方式请求 json传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const putJson = (url, params, level) =>
  service(getConfig(url, 'put', true, params, level))
  .then(res => successback(res))
/**
 * put方式请求 表单传参
 * @param url 请求url
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const put = (url, params, level) =>
  service(getConfig(url, 'put', false, params, level))
    .then(res => successback(res))

/**
 * @param url 请求url
 * @param method get,post,put,delete
 * @param isJson 是否json提交参数
 * @param params 参数
 * @param level 0:无加密，1：参数加密，2: 签名+时间戳； 默认0
 */
const getConfig = (url, method, isJson, params, level = 0) => {
  const config_ = {
    url,
    method,
    // params, data,
    headers: {
      level
    }
  }
  // 时间戳
  if (level === 1) { // 加密
    params = { encrypt: aes.en(JSON.stringify(params)) }
  } else if (level === 2) { // 签名
    const timestamp = new Date().getTime()
    // 获取token
    let token = store.state.token
    console.log('token:', token)
    if (!token) {
      token = JSON.parse(sessionStorage.getItem('user')).token
      store.state.token = token
    }
    // 签名串
    const signstr = sign(token, timestamp, params)
    console.log('token', token)
    console.log('signstr', signstr)
    config_.headers = {
      level,
      timestamp,
      signstr
    }
  }
  // 表单提交参数
  if (!isJson) {
    config_.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    config_.responseType = 'text'
    config_.transformRequest = [function (data) {
      return param2String(data)
    }]
  }
  // 设置参数
  if (method in { 'get': true, 'delete': true }) {
    config_.params = params
  } else if (method in { 'post': true, 'put': true }) {
    config_.data = params
  }
  return config_
}

// 参数转换
const param2String = data => {
  console.log('data', data)
  if (typeof data === 'string') {
    return data
  }
  let ret = ''
  for (const it in data) {
    let val = data[it]
    if (typeof val === 'object' && //
      (!(val instanceof Array) || (val.length > 0 && (typeof val[0] === 'object')))) {
      val = JSON.stringify(val)
    }
    ret += it + '=' + encodeURIComponent(val) + '&'
  }
  if (ret.length > 0) {
    ret = ret.substring(0, ret.length - 1)
  }
  return ret
}

// 成功回调函数
const successback = res => {
  if (res.status === 200 && res.data.code !== 20000) {
    const errMsg = { '30002': '对不起无权限', '30003': '验签失败' }
    const msg = errMsg[res.data.code]
    if (msg) {
      notification({
        message: '友情提示',
        description: res.data.message
      })
    }
    return Promise.reject(res)
  }
  return res.data
}

export {
  installer as VueAxios,
  service as axios,
  get,
  postJson,
  post,
  del,
  putJson,
  put
}
